from rest_framework import status
from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from rest_framework_jwt.settings import api_settings
from .serializers import QQRegisterSerializer
from .utils import OauthQQ
import logging
from .models import OAuthQQUser

logger = logging.getLogger('meiduo')


# Create your views here.

class QQTokenView(GenericAPIView):
    """
    获取access_token
    GET     /oauth/qq/users/?code=xxx
    POST    /oauth/qq/users/
    """
    # 绑定序列化器
    serializer_class = QQRegisterSerializer

    def get(self, request):
        # 获取qq给的code
        code = request.query_params.get("code")
        if code is None:
            return Response({'message': "缺少参数"}, status=status.HTTP_400_BAD_REQUEST)

        qq = OauthQQ()
        try:
            access_token = qq.get_access_token(code)
            openid = qq.get_openid(access_token)
        except Exception as e:
            logger.error(e)
            return Response({'message': '服务异常'}, status=status.HTTP_503_SERVICE_UNAVAILABLE)

        # 判断qq是否绑定了用户

        try:
            qq_user = OAuthQQUser.objects.get(openid=openid)

        except OAuthQQUser.DoesNotExist:
            # 没有绑定的话会跳转到创建绑定该qq新用户,用itsdangerous加密
            token = OAuthQQUser.generate_save_user_token(openid)
            return Response({'access_token': token})
        else:
            # qq已经绑定了用用户直接用jwt加密
            # 查询用户,生成登录token
            user = qq_user.user
            jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
            jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

            payload = jwt_payload_handler(user)
            token = jwt_encode_handler(payload)

            response = Response({
                'token': token,
                'user_id': user.id,
                'username': user.username
            })
            return response

    # 绑定qq与用户
    def post(self, request):
        '''
        # 用户需要填写手机号、密码、图片验证码、短信验证码
        # 如果用户未在美多商城注册过，则会将手机号作为用户名为用户创建一个美多账户，并绑定用户
        # 如果用户已在美多商城注册过，则检验密码后直接绑定用户
        :param request:
                        mobile	        str	是	手机号
                        password	    str	是	密码
                        sms_code	    str	是	短信验证码
                        access_token	str	是	凭据 （包含openid)
        :return post:
                        token	        str	是	JWT token
                        user_id	        int	是	用户id
                        username	    str	是	用户名

        '''
        # 用户需要填写手机号、密码、图片验证码、短信验证码
        ## 使用序列化器对前端请求进行校验
        ### 获取序列化器
        serializer  = self.get_serializer(data=request.data)
        ### 序列化器内部校验前端数据
        serializer.is_valid(raise_exception=True)
        ### 序列化器保存并返回一个user对象（保存和CU相关）
        user = serializer.save()  # 返回的用户是已经注册了的或者是刚刚注册好的
        # jwt加密生成token
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        token = jwt_encode_handler(payload)

        response = Response({
            'token': token,
            'user_id': user.id,
            'username': user.username
        })

        return response

class QQAuthURLView(APIView):
    """
     实现出现QQ授权登录视图
     GET /oauth/qq/statues/
    """

    def get(self, request):
        # 生成auth_url
        # https://graph.qq.com/oauth2.0/authorize
        # 请求参数请包含如下内容：
        # response_type   必须      授权类型，此值固定为“code”。
        # client_id       必须      申请QQ登录成功后，分配给应用的appid。
        # redirect_uri    必须      成功授权后的回调地址，一定是注册appid时填写的主域名下的地址，建议设置为网站首页或网站的用户中心。注意需要将url进行URLEncode。
        # state           必须      client端的状态值。用于第三方应用防止CSRF攻击，成功授权后回调时会原样带回。请务必严格按照流程检查用户与state参数状态的绑定。
        # scope           可选      scope=get_user_info

        # 获取state
        state = request.query_params.get('state')

        qq = OauthQQ()
        url = qq.get_auth_url(state)
        return Response({'auth_url': url})
